一.需求概述
   统计老王一天吃饭,睡觉,玩游戏的时间
二.AOP思想(Aspect Oriented Programming)
  面向切面编程
   切面(同一层面的不同方法之间共性行为)
三.通过静态代理实现AOP
   1.定义一个代理类实现和被代理类相同的接口,相当于代理接口中这些方法
   2.代理类专注同一层面不同方法的共性行为(所有行为都要统计时间),被代理类专注于自身逻辑(吃,玩,睡觉行为)
   静态指的是编译时期已经把代理类写死
   静态代理缺点:
    1.如果接口中的方法比较多,我们代理类实现大量方法,代理类代码会非常臃肿
    2.同一层面不同方法的共性行为(代码)复用性非常低,每代理一个方法,我们都要写一次

四.动态代理实现AOP
		/**
		 * 动态代理实现AOP:
		 *   动态指的是:在程序运行时,由JVM为我们自动生成代理类(隐式代理)
		 *
		 * 用到的Class类中的方法:
		 *    ClassLoader getClassLoader()
		 *           返回该类的类加载器。
		 *
		 *    Class<?>[] getInterfaces()
		 *           确定此对象所表示的类或接口实现的接口。
		 *
		 * 我们需要通过Proxy类的方法来实现动态代理
		 *   static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
		 *           返回一个指定接口的代理类实例，该接口可以将方法调用指派到指定的调用处理程序。
		 *
		 *   第一个参数:传递一个类加载器,用来加载JVM生成的代理类,我们一般使用和被代理类(老王类)相同的加载器
		 *   第二个参数:传递代理类和被代理类实现的接口(一个类实现的接口有可能多个,所以用数组接收)
		 *   第三个参数:传递一个InvocationHandler接口实现类对象,InvocationHandler实现类对象绑定在代理类对象上
		 *   返回值:底层会返回由JVM生成的代理类的一个实例
		 *
		 *
		 *
		 */
		class Proxy{

			protected InvocationHandler h;

			protected Proxy(InvocationHandler h) {
				this.h = h;
			}

		}


		/*JVM底层生成的代理类*/
		/*
		 InvocationHandler接口中的invoke方法
		     Object invoke(Object proxy, Method method, Object[] args)
		*/
		class $Proxy1 extends Proxy implements OneDay{

			public $Proxy1(InvocationHandler ih){
				super(ih);
			}


			public void eat(){
				super.h.invoke(this,OneDay.class.getMethod("eat"),null);
			}
			public void play(){
				super.h.invoke(this,OneDay.class.getMethod("play"),null);
			}
			public void sleep(){
				super.h.invoke(this,OneDay.class.getMethod("sleep"),null);
			}
		}
     动态代理的优点:
       1.不用我们自定义一个代理类实现和被代理类相同的接口,实现接口中的大量方法
          由JVM帮我们创建这个代理类,简化代码
       2.对于同一层面不同方法之间的共性行为我们只需要写一次,从而提高代码复用性
五.Java中的注解
   a.注解概述
     注解相当于是一种标记,交给java编译器或者程序来解析,当java编译器和程序解析到相应的注解就会执行相应的操作
     KFC
   b.Java中常见注解
		/**
		 * @Override 交给编译器解析,编译器会检查该方法是否重写父类对应的方法,如果该方法没有重写父类的方法,那么编译直接报错
		 * @Deprecated 交给编译器解析,代表该方法已过时,当我们调用该方法的时候,会在方法名上加一个删除线
		 *              已过时的方法可以使用,但是不推荐使用
		 * // @param 文档注释相关的注解 可以在后面对该参数进行信息描述
		 * // @return 文档注释相关的注解 可以在后面对该方法的返回值进行描述
		 * // @throws  文档注释相关的注解 可以在后面对该方法声明的异常进行描述
		 */
   c.Java中的定义注解
     格式:
      //元注解(可写可不写)
      public @interface 注解名称{
   	     //注解属性
	     数据类型 属性名称();
	     数据类型 属性名称() default 默认值;//代表当前属性的默认值
      }
      注解中属性的数据类型:
        1.Java中八大基本类型
        2.String,Class,enum,注解类型
        3.以上所有类型的一维数组
     使用:
		public @interface MyAnnotation {
			String name(); //定义一个String类型name属性
			int num() default 0;//定义一个int类型num属性,并且默认值为0
			String[] colors() default {"white","black"};//定义一个String[]类型的colors属性,并且默认值为{"white","black"}
		}
		public @interface MyAnnotation02 {
			int value();

			String name() default "老王";

			Color color() default Color.GREEN;
		}
    d.元注解(注解上的注解)
     @Target:指定该注解能使用的位置,默认定义的注解可以使用在任意位置
		TYPE:表明该注解可以使用在类上
		FIELD:表明该注解可以使用在成员变量上
		METHOD:表明该注解可以使用在成员方法上
		PARAMETER:表明该注解可以使用在参数上
		CONSTRUCTOR:表明该注解可以使用在构造方法上
		LOCAL_VARIABLE:表明该注解可以使用在局部变量上
		ANNOTATION_TYPE:表明该注解可以使用在其它注解上
		PACKAGE:表明该注解可以使用在包上
		TYPE_PARAMETER:表明该注解可以使用在泛型上
		TYPE_USE:表明该注解可以使用在任意位置上
     @Retention:指定注解的生命周期(存活时间),不指定默认生命周期是RetentionPolicy.CLASS
		RetentionPolicy.SOURCE:指定该注解只存在于源码(.java文件)阶段,编译器编译该.java文件后生成的.class文件中就不再有该注解
		                       例如@Override
		RetentionPolicy.CLASS:指定该注解存在源码(.java)阶段,编译器器编译该.java文件后生成的.class文件中依然有该注解
				              当程序运行的时候(把这个.class加载到jvm时)会丢弃该注解
				              如果该注解指名为这个RetentionPolicy.CLASS,那么该类对应的字节码对象中就没有该注解
		RetentionPolicy.RUNTIME
				            指定该注解存在源码(.java)阶段,编译器器编译该.java文件后生成的.class文件中依然有该注解
                             而且程序运行时(把这个.class加载到jvm时)依然存在该注解
    e.通过反射获取类上和方法上的注解
		/**
		 * 获取类上和方法上的注解
		 * Class类中的方法:
		 *  boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
		 *           判断该类上是否有指定的注解,如果有返回true,否则返回false
		 *  public <A extends Annotation> A getAnnotation(Class<A> annotationClass)
		 *         获取该类上指定的注解
		 * Method类中:
		 *  public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
		 *   判断该方法上是否有指定的注解,如果有返回true,否则返回false
		 *  public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
		 *     获取该方法上指定的注解
		 */

